import { ColliderUpdateType, SysOrder } from "../../GameDef";
import { Grid } from "../../lib/kgame/d2/Grid";
import { QuadTree } from "../../lib/kgame/d2/QuadTree";
import { ECSFilterEvent, IECSFilter } from "../../lib/kgame/ecs/ECSFilter";
import { ECSSys } from "../../lib/kgame/ecs/ECSSys";
import { ColliderCmp } from "../cmp/ColliderCmp";
import { ColliderMgr } from "../scmp/ColliderMgr";

/**
 * 碰撞系统
 */
export class ColliderSys extends ECSSys {

    get updateOrder(): number {
        return SysOrder.collider;
    }

    get ifilter(): IECSFilter {
        return { includeOne: [ColliderCmp] }
    }

    onAdd(): void {
        const mgr = this.scene.getCmp(ColliderMgr);

        this.filter.on(ECSFilterEvent.cmpAdd, data => {
            const col = data as ColliderCmp;
            mgr.onColliderAdd(col);
        }, this);

        this.filter.on(ECSFilterEvent.cmpRemove, data => {
            const col = data as ColliderCmp;
            mgr.onColliderRemove(col);
        }, this);
    }

    onUpdate(): void {
        const mgr = this.scene.getCmp(ColliderMgr);

        mgr.clearQuadTrees();
        mgr.colliderTypeMap.forEach((cols, type) => {
            const cont = mgr.containerMap.get(type);
            if (cont instanceof QuadTree) {
                cols.forEach(col => {
                    col.collidersOther.length = 0;
                    col.collidersSelf.length = 0;
                    cont.addItem(col, col.shape.worldAABB);
                });
            } else if (cont instanceof Grid) {
                cols.forEach(col => {
                    col.collidersOther.length = 0;
                    col.collidersSelf.length = 0;
                    if (col.updateType === ColliderUpdateType.update) {
                        cont.updateItem(col, col.shape.worldAABB);
                    }
                });
            } else {
                cols.forEach(col => {
                    col.collidersOther.length = 0;
                    col.collidersSelf.length = 0;
                });
            }
        });

        mgr.collisionGroupMap.forEach((cols, group) => {
            mgr.colliderTypeMap.forEach((_, type) => {
                //碰撞组检测
                if (group & type) {
                    cols.forEach(col => {
                        const cont = mgr.containerMap.get(type);
                        cont.getCoverItems(col.shape.worldAABB).forEach(target => {
                            this.testCollide(col, target)
                        });
                    });
                }
            });
        })
    }

    /**
     * 碰撞检测
     * @param col 
     * @param target 
     */
    testCollide(col: ColliderCmp, target: ColliderCmp) {
        if (col.passId === target.passId) {
            return; //跳过相同passId的
        }

        if (col.shape.testCollide(target.shape)) {
            //检测到碰撞
            target.collidersSelf.push(col);
            col.collidersOther.push(target);
        }
    }
}